package jnpf.message.service.impl.open;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import com.alibaba.fastjson.JSONObject;
import jnpf.base.ActionResult;
import jnpf.constant.MsgCode;
import jnpf.message.model.message.OpenBaseModel;
import jnpf.message.model.message.OpenDeptModel;
import jnpf.message.service.SynThirdInfoService;
import jnpf.message.service.ThirdOpenService;
import jnpf.message.util.SynThirdConsts;
import jnpf.permission.entity.OrganizeEntity;
import jnpf.permission.service.OrganizeService;
import jnpf.util.CacheKeyUtil;
import jnpf.util.RedisUtil;
import jnpf.util.StringUtil;
import jnpf.util.UserProvider;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
@Log4j2
@RequiredArgsConstructor
public class ThirdOpenOrgServiceImpl implements ThirdOpenService {
	private final SynThirdInfoService synThirdInfoService;

	private final OrganizeService organizeService;

	private final UserProvider userProvider;
	private final RedisUtil redisUtil;
	private final CacheKeyUtil cacheKeyUtil;

	@Override
	@Transactional(rollbackFor = Exception.class)
	public Object beforeProcess(OpenBaseModel openBaseModel, Map<String, OpenDeptModel> organizeMap) {
		OpenDeptModel deptEntity = (OpenDeptModel) openBaseModel;
		OpenBaseModel.OperationType operationType = deptEntity.getType();
		String description = "";
		String deptId = deptEntity.getDeptId();
		try {
			switch (operationType) {
				case ADD:
				case EDIT:
				case ENABLE:
					String extension = deptEntity.getExtension();
					JSONObject extendObj = JSONObject.parseObject(extension);
					//判定是否已经存在
					OrganizeEntity orgInfo = organizeService.getInfo(deptId);
					boolean isFilter = false;
					if (Objects.isNull(orgInfo)) {
						orgInfo = new OrganizeEntity();
					} else {
						isFilter = true;
					}
					orgInfo.setId(deptId);
					Integer type = extendObj.getInteger("type");
					orgInfo.setCategory(type == 1 ? SynThirdConsts.OBJECT_TYPE_COMPANY : SynThirdConsts.OBJECT_TYPE_DEPARTMENT);
					orgInfo.setParentId(deptEntity.getParentId());
					// 通过组织id获取父级组织
					String organizeIdTree = "";
					if (MapUtil.isEmpty(organizeMap)) {
						organizeIdTree = deptId + "," + organizeService.getOrganizeIdTree(orgInfo);
					} else {

						organizeIdTree = getTree(deptEntity, organizeMap);
						String[] organizeIds = organizeIdTree.split(",");
						// 检查数组是否有元素并取最后一个
						if (organizeIds.length > 0) {
							String lastOrganizeId = organizeIds[organizeIds.length - 1];
							// 你可以在这里使用 lastOrganizeId
							if (!lastOrganizeId.equals("0")) {
								description = "存在脏数据";
								return null;
							}
							organizeIdTree = organizeIdTree.substring(0, organizeIdTree.length() - 2);
						}
					}
					orgInfo.setOrganizeIdTree(organizeIdTree);
					orgInfo.setEnCode(deptId);
					orgInfo.setFullName(deptEntity.getName());
					orgInfo.setSortCode(deptEntity.getOrder() != null ? deptEntity.getOrder() : 1L);
					if (CollectionUtil.isNotEmpty(deptEntity.getDeptManagerUserIdList())) {
						orgInfo.setManagerId(deptEntity.getDeptManagerUserIdList().stream().collect(Collectors.joining(",")));

					}
					if (CollectionUtil.isNotEmpty(deptEntity.getDeptDirectSupervisorUserIdList())) {
						orgInfo.setDirectSupervisorId(deptEntity.getDeptDirectSupervisorUserIdList().stream().collect(Collectors.joining(",")));
					}

					if (CollectionUtil.isNotEmpty(deptEntity.getDeptResponsibleLeaderUserIdList())) {
						orgInfo.setResponsibleLeaderId(deptEntity.getDeptResponsibleLeaderUserIdList().stream().collect(Collectors.joining(",")));
					}
					if (type == 1) {
						if (organizeService.isExistByFullName(orgInfo, false, isFilter)) {
							description = MsgCode.EXIST001.get();
							break;
						}
						if (organizeService.isExistByEnCode(orgInfo.getEnCode(), orgInfo.getId())) {
							description = MsgCode.EXIST002.get();
							break;
						}
					} else {
						OrganizeEntity entity = organizeService.getById(deptEntity.getParentId());
						// 判断同一个父级下是否含有同一个名称
						if (organizeService.isExistByFullName(orgInfo, false, false)) {
							description = "部门" + MsgCode.EXIST001.get();
							break;
						}
						// 判断同一个父级下是否含有同一个编码
						if (organizeService.isExistByEnCode(orgInfo.getEnCode(), entity.getId())) {
							description = "部门" + MsgCode.EXIST002.get();
							break;
						}
					}
					return orgInfo;
				case DELETE:
				case DISABLE:
					ActionResult<String> delete = organizeService.delete(deptId);
					description = delete.getMsg();
				default:
			}
		} catch (Exception e) {
			description = e.getMessage();
			e.printStackTrace();
			throw e;

		} finally {
			saveSynThirdInfoEntity(operationType, SynThirdConsts.DATA_TYPE_ORG, deptId, StringUtils.isBlank(description) ? 2 : 1, description, synThirdInfoService, userProvider);
		}
		return null;
	}

	private String getTree(OpenDeptModel openDeptModel, Map<String, OpenDeptModel> organizeMap) {
		List<String> organizeParentIdList = new ArrayList<>();
		getOrganizeIdTree(openDeptModel.getDeptId(), organizeParentIdList, organizeMap);
		return organizeParentIdList.stream().collect(Collectors.joining(","));
	}

	public void getOrganizeIdTree(String organizeId, List<String> organizeParentIdList, Map<String, OpenDeptModel> organizeMap) {
		OpenDeptModel entity = organizeMap.get(organizeId);
		if (entity != null) {
			if (organizeParentIdList.contains(organizeId)) {
				//存在循环依赖
				return;
			}
			organizeParentIdList.add(entity.getDeptId());
			if (StringUtil.isNotEmpty(entity.getParentId())) {
				getOrganizeIdTree(entity.getParentId(), organizeParentIdList, organizeMap);
			}
		}
	}

	@Override
	@Transactional(rollbackFor = Exception.class)
	public void afterProcess(List<Object> result) {
		organizeService.saveOrUpdateBatch(result.stream().map(e -> (OrganizeEntity) e).filter(Objects::nonNull).collect(Collectors.toList()));
		redisUtil.remove(cacheKeyUtil.getOrganizeInfoList());
	}
}
